/**
在 Webpack 中，提取 CSS 文件是一种优化技术，旨在将 CSS 从 JavaScript 打包文件中分离出来，生成独立的 CSS 文件。这种做法可以提高加载性能和维护性，因为浏览器可以并行加载 CSS 和 JavaScript 文件，且 CSS 文件的缓存也更加有效。
  1. 为什么要提取 CSS 文件？
  - 性能优化: 将 CSS 提取到单独的文件中，可以让浏览器并行加载 CSS 和 JavaScript，提高页面加载速度。
  - 缓存: 用户在访问页面时，CSS 文件可以被浏览器缓存，避免重复下载，从而减少网络请求。
  - 更好的维护性: 将 CSS 和 JavaScript 分开，可以使项目结构更加清晰，便于管理和维护。

  2. 使用 `mini-css-extract-plugin`
  在 Webpack 中，提取 CSS 文件通常使用 `mini-css-extract-plugin` 插件。该插件可以将 CSS 提取为独立的文件，而不是将其嵌入到 JavaScript 中。
   安装插件
  首先，通过 npm 安装 `mini-css-extract-plugin`：

  ```bash
  npm install --save-dev mini-css-extract-plugin
  ```

   配置 Webpack
  在 `webpack.config.js` 中配置 `mini-css-extract-plugin` 以提取 CSS 文件。

  ```javascript
  const path = require('path');
  const MiniCssExtractPlugin = require('mini-css-extract-plugin');

  module.exports = {
      entry: './src/index.js', // 入口文件
      output: {
          filename: 'bundle.js', // 输出的 JavaScript 文件
          path: path.resolve(__dirname, 'dist'), // 输出目录
      },
      module: {
          rules: [
              {
                  test: /\.css$/, // 匹配所有 CSS 文件
                  use: [
                      MiniCssExtractPlugin.loader, // 提取 CSS
                      'css-loader', // 处理 CSS 文件
                  ],
              },
          ],
      },
      plugins: [
          new MiniCssExtractPlugin({
              filename: 'styles.css', // 提取的 CSS 文件名
          }),
      ],
      mode: 'production', // 或 'development'
  };
  ```

  3. 使用 Sass 或 Less
  如果使用 Sass 或 Less 等预处理器，也可以通过 `mini-css-extract-plugin` 提取相应的 CSS 文件。需要安装相应的加载器，如 `sass-loader` 或 `less-loader`。

   示例配置（Sass）：

  ```javascript
  module.exports = {
      // ...
      module: {
          rules: [
              {
                  test: /\.scss$/, // 匹配所有 Sass 文件
                  use: [
                      MiniCssExtractPlugin.loader,
                      'css-loader',
                      'sass-loader', // 处理 Sass 文件
                  ],
              },
          ],
      },
      // ...
  };
  ```

  4. 注意事项
  - 顺序: 确保 CSS 的加载顺序正确，特别是在使用多个 CSS 文件时，可能需要调整加载顺序以避免样式冲突。
  - 生产环境: 在开发环境中，通常不需要提取 CSS，因为热重载会更方便。在生产环境中，提取 CSS 可以提高性能。
  - 依赖管理: 确保 CSS 文件中的依赖（如字体、图片等）能够正确解析。

  总结
  提取 CSS 文件是 Webpack 中一种有效的优化技术，通过使用 `mini-css-extract-plugin`，可以将 CSS 从 JavaScript 中分离出来，生成独立的 CSS 文件。这不仅提高了页面加载性能，还改善了缓存机制和代码的可维护性。希望这个总结对你理解 Webpack 中提取 CSS 文件的过程有所帮助！
 */
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { ProvidePlugin } = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: "production",
  devtool: false,
  entry: "./src/main.js",
  output: {
    clean: true,
    path: path.resolve(__dirname, "./build"),
    filename: "js/[name]_chunk.js", // [name]占位符
    // 单独针对分包的文件进行命名
    chunkFilename: "js/[name]_chunk.js",
  },
  /**
   * externals: 排除某些包不需要进行打包
   */
  // externals: {
  //   /**
  //    * key属性名: 排除的框架名称
  //    * value属性值: 从CDN地址请求下来的js中提供对应的名称
  //    */
  //   react: "React",
  //   axios: "axios",
  // },
  /**
   * resolve: 配置模块解析
   * extensions: 配置解析模块时自动补全的扩展名
   */
  resolve: {
    extensions: [".js", ".json", ".wasm", ".jsx", ".ts"],
  },
  devServer: {
    static: ["public", "content"],
    port: 3000,
    compress: true,
    proxy: [
      {
        context: () => true,
        target: "http://localhost:1234",
        pathRewrite: { "^/api": "" },
      },
    ],
    historyApiFallback: true,
  },
  optimization: {
    chunkIds: "deterministic", // 生成文件名时使用确定的文件名
    runtimeChunk: {
      name: "runtime", // 将runtime相关的代码单独打包
    },
    splitChunks: {
      // 分包配置
      chunks: "all", // 对所有模块都进行分割
      minSize: 10, // 分割的模块最小为10kb
      // 自己对需要进行拆包的内容进行分包
      cacheGroups: {
        utils: {
          test: /utils/,
          filename: "js/[id]_utils.js",
        },
        // vendors表示: 将node_modules中的包单独打包
        vendors: {
          // /node_modules/
          // window上面 /\
          // mac上面 /
          test: /[\\/]node_modules[\\/]/,
          filename: "js/[id]_vendors.js",
        },
      },
    },
    // 压缩配置
    minimizer: [
      new TerserPlugin({
        extractComments: false, // 不将注释提取到单独的文件中
      }),
    ],
  },
  module: {
    rules: [
      {
        test: /\.jsx$/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /\.js$/,
        use: "babel-loader",
      },
      {
        test: /\.css$/,
        use: [
          // 'style-loader' // 将css文件变成style标签插入到html文件中, 开发阶段
          MiniCssExtractPlugin.loader, // 将css文件变成style标签插入到html文件中, 生产阶段
          "css-loader", // 将css文件变成commonjs模块加载到js文件中
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./index.html", // 模板文件
    }),
    new ProvidePlugin({
      axios: ["axios", "default"],
      dayjs: "dayjs",
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
      chunkFilename: "css/[name]_chunk.css",
    }),
  ],
};
